﻿#ifndef PST_TEXTFILEPARSER_H
#define PST_TEXTFILEPARSER_H

#include <QObject>
#include <QList>
#include <QHash>
#include <QVector>
#include <vtkObject.h>
#include <vtkSmartPointer.h>
#include "InfomationCurve2DBasical.h"
#include "TextArrayMetaHander.h"
class vtkTable;
class vtkPlotLine;
class vtkPoints;
class vtkDelimitedTextReader;

namespace pst
{
    class TextFileParser : public QObject //, public vtkObject
    {
        Q_OBJECT
    public:
        explicit TextFileParser(QObject* parent = Q_NULLPTR);
        ~TextFileParser();

    public:
        // 只用于存储，不用于读取文件
        void SetFileName(const QString& fileName);
        QString GetFileName();

        void SetInputTable(vtkTable* table);
        vtkTable* GetInputTable();
        // vtkDelimitedTextReader* getTextReader();

        // json中的文件类型result_type
        void setFileDealType(int type);
        int getFileDealType();

        // 0为标量，1为实部虚部， 2为幅度相位
        void setFileComponentType(int type);
        int getFileComponentType();

        bool Update(); // 要改

        /// @brief 设置是否取对数
        /// @param log 是否取对数
        void SetLogTheData(bool log);
        /// @brief 获取是否设置取了对数
        /// @return 是否取对数
        bool GetLogTheData();

        /// @brief 设置是否归一化
        /// @param log 是否归一化
        void SetNormalizeTheData(bool normolized);
        /// @brief 获取是否设置归一化
        /// @return 是否归一化
        bool GetNormalizeTheData();

        /// @brief 设置取对数时的因子，默认10
        /// @para factory 因子
        void SetLogCoefficients(double factory);

        /// @brief  获取取对数时的因子，默认10
        /// @return 因子
        double GetLogFactory();

        /// @brief 获取原始表格数据
        /// @return
        vtkTable* getOriginalTable();

        /// @brief 获取标准化后的表格数据
        vtkSmartPointer<vtkTable> getStandardTable();

        QVector<QString> getEachColNameOfKey();
        QVector<QString> getEachColUnitOfKey();
        QVector<QVector<double>> getEachColDataOfKey();

        QVector<QString> getEachColGroupNameOfValue(); // 按组名划分列，每一列数据的组名（一组可能包含多列）
        QVector<QString> getEachColNameOfValue();
        QVector<QString> getEachColUnitOfValue();
        QVector<QVector<double>> getEachColDataOfValue();

        QHash<QVector<double>, QVector<double>> getValueMatrix();

        /// @brief 设置扫描参数的下标
        /// @param index 表明那一列将作为扫描参数被遍历
        void setScanParameterIndex(int index);
        int getScanParameterIndex();
        inline void setSecondScanParameterIndex(int index) { m_secondScanParaIndex = index; };
        inline int getSecondScanParameterIndex() const { return m_secondScanParaIndex; };

        void setOtherKeyParameter(const QVector<QVector<double>>& keyParaList);
        QVector<QVector<double>> getOtherKeyParameter();

        /// @brief 获得生成的结果，valueId在有多个值时，一个key对应多个value
        /// @param valueId 需要
        /// @param returnTable 所有结果返回到一个表中，第一列为扫描参数，其他列为结果曲线
        void getChosenLinesFromKey(QList<int> valueId, vtkTable* returnTable);

        void getChosenLinesFromKey(QList<QPair<int, int>> valueId,
                                   QList<Info2DPointer>& yList);
        void getChosenLinesFromMultiKey(QList<QPair<int, int>> valueId,
                                        QList<Info2DPointer>& yList);

        /// 用于极坐标绘图
        /// note: 此函数仅用于获取原来是 "Theta||deg||key","Phi||deg||key","Frequency||GHz||key","Gain||None||value"格式的文件数据，
        /// note:内部将球坐标转为直角坐标结果，获取的为直角坐标点
        /// @brief 获得生成的结果，valueId在有多个值时，一个key对应多个value
        /// @param valueId 需要
        /// @param radiusBestRange 用于标签显示的最恰最小最大值
        /// @param minValue 半径轴最小值，小于该值，置为0. 否则数值应加上最小值。
        /// resultPointsList 每个vtkPoints代表一个曲线结果
        void getChosenPointsListFromKey(QList<int> valueId,
                                        QList<vtkSmartPointer<vtkPoints>>& resultPointsList,
                                        QList<vtkSmartPointer<vtkPoints>>& resultPointsList_sphere,
                                        QList<QString>& lineName, double radiusBestRange[2], bool log, bool normalize, double minValue, bool enableCustomRange);

        QString getErrorMessage() const;

        void SetOtherList(const QList<TextFileParser*>& otherList)
        {
            m_otherList = otherList;
        }

        QList<TextFileParser*> GetOtherList() const
        {
            return m_otherList;
        }

        void SetGeometryFileName(const QStringList& geometryFileName)
        {
            m_geometryFileName = geometryFileName;
        }

        QStringList GetGeometryFileName() const
        {
            return m_geometryFileName;
        }

        /// @brief 根据扫描参数和
        // void generateChosenKeyList();
        // componentIndex 0:幅度 1：相位 2：实部 3：虚部 4 ：标量
        // 不包含key列的下标
        int getRealValueIndex(int valueIndex, int componentIndex);

        TextArrayMetaStruct getDataInfo(int valueIndex);
        TextArrayMetaStruct getDataInfoByRealValueIndex(int valueIndex);

        /// @brief 文件写出至工程文件
        QDomElement& writeToProjectFile(QDomDocument* doc, QDomElement* element, bool isdiso = false);

        /// @brief 从工程文件读入数据
        void readFromProjectFile(QDomNodeList* nodelist, bool isdiso = false);

    private:
        // bool ReadTxtToVTKTable(const QString& filename);

        /// @brief 解析文件表头，分析哪些是key, 哪些是value，并分别获取名字
        bool parseTitleName(vtkTable* inputTable,
                            QVector<QString>& eachColNameOfKey, QVector<QString>& eachColUnitOfKey,
                            QVector<QString>& eachColNameOfValue, QVector<QString>& eachColUnitOfValue);

        void clearData();

        bool generateValueMatrix();

        void FilterRows(vtkTable* table);

        void UnitConversion(const QString& unit, double& value);
        void UnitChange();
        void changeMetaUnit(vtkTable* table);
        //// 根据数据类型（m_fileDealType和 m_fileComponentType） 扩展表格
        // bool expandTable();

        /// @brief 对单位进行转换,只更改名字
        void doUnitNameConversion(QString& unit);

    private:
        QString m_fileName;
        vtkSmartPointer<vtkTable> m_originalTable; // 读取的原始表格
        vtkSmartPointer<vtkTable> m_standardTable; // 标准表格（进行了单位转换的）

        QVector<QString> m_eachColNameOfKey;         // 每一Key列的列名字
        QVector<QString> m_eachColUnitOfKey;         // 每一Key列的单位
        QVector<QVector<double>> m_eachColDataOfKey; // 每一key列包含的数据
        int m_keyLenth;                              // 每个key应该有的的长度

        QVector<QString> m_eachColGroupNameOfValue; // 按组名划分列，每一列数据的组名（一组可能包含多列）

        QVector<QString> m_eachColNameOfValue;         // 每一value列的列名字
        QVector<QString> m_eachColUnitOfValue;         // 每一value列的单位
        QVector<QVector<double>> m_eachColDataOfValue; // 每一value列包含的数据
        int m_valueLenth;                              // 每个value应该有的的长度, 即每个key对应的value有多少个

        QHash<QVector<double>, QVector<double>> m_valueMatrix; // key为扫描参数, value为对应的值

        bool m_isSetLog;
        bool m_isSetNormalized;
        double m_logFactory; // 取对数时的系数

        int m_scanParaIndex;                      // 选择作为扫描参数的下标
        int m_secondScanParaIndex;                // 选择作为第二个扫描参数的下标
        QVector<QVector<double>> m_chosenKeyList; // 选择的其他Key的列表

        vtkTable* m_chosenDataTable; // 选择的数据生成的临时表，用于生成曲线

        QString m_errorMessage;

        QList<TextFileParser*> m_otherList;

        // QString m_textHeaderComment; // 表头注释，如版本等，文件的第0行
        // QString m_textHeader;        // 表头，文件的第一行
        //  QList<vtkSmartPointer<vtkPlotLine>>

        // json中的文件类型result_type
        // 是文件的类型
        // 体电场分布（0）面电场分布（1） 点电场（探针点）（2） 表面场分布（3）表面电流密度（4） 空间电势分布（5）
        // 表面电势分布（6） 方向图（7）  S参数（8）  驻波比（9）  电压（10）
        // 电流（11） 附着点路径（14）   面电势分布（15） 干扰关联矩阵（12）  SAR（13）
        int m_fileDealType;
        // 0为标量，1为实部虚部， 2为幅度相位
        int m_fileComponentType;
        QStringList m_geometryFileName;
    };
} // namespace pst

#endif
